package com.threeti.mecool.web.controller.admin;

import com.threeti.mecool.core.application.AdminService;
import com.threeti.mecool.core.domain.model.SalesScoringCategory;
import com.threeti.mecool.core.domain.model.plan.ProjectCriticalJob;
import com.threeti.mecool.core.domain.model.plan.pojo.*;
import com.threeti.mecool.core.domain.model.project.Project;
import com.threeti.mecool.core.domain.model.project.ProjectCategory;
import com.threeti.mecool.core.infrastructure.persistence.SalesScoringCategoryRepository;
import com.threeti.mecool.core.infrastructure.persistence.plan.*;
import com.threeti.mecool.core.infrastructure.persistence.project.ProjectCategoryRepository;
import com.threeti.mecool.core.infrastructure.persistence.project.ProjectRepository;
import com.threeti.mecool.framework.util.Lists;
import com.threeti.mecool.framework.util.PageHandler;
import com.threeti.mecool.web.assembler.PlanAssembler;
import com.threeti.mecool.web.util.RequestUtil;
import com.threeti.mecool.web.util.WebResponse;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @author Yuqi Chou
 * @version Jun 26, 2012 5:32:11 PM
 */
@Controller
@RequestMapping("/admin")
public class TaskActionStepController {

    public static final Logger logger = LoggerFactory.getLogger(TaskActionStepController.class);

    @Autowired
    private TaskActionDataTypeRepository taskActionDataTypeRepository;

    @Autowired
    private TaskRepository taskRepository;

    @Autowired
    private JobRepository jobRepository;

    @Autowired
    private AdminService adminService;

    @Autowired
    private ProjectCategoryRepository projCatRepo;

    @Autowired
    private ProjectRepository projectRepository;

    @Autowired
    private ProjectCriticalJobRepository projectCriticalJobRepository;

    @Autowired
    private SalesScoringCategoryRepository salesScoringCategoryRepository;

    @Autowired
    private PlanJobRepository planJobRepository;

    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping(value = "/newStepIdentityForm.html")
    public void newStepIdentityForm(Map modelMap) {
        modelMap.put("taskAction", TaskAction.values());
    }

    @SuppressWarnings({"rawtypes"})
    @RequestMapping(value = "/saveStepIdentity.html")
    public String saveStepIdentity(Map modelMap,
                                   int actionId,
                                   String actionName) {
        try {
            TaskActionDataType taskActionDataType = new TaskActionDataType(actionId, actionName);
            taskActionDataType.setUpdatedAt(new Date());
            taskActionDataTypeRepository.saveAndFlush(taskActionDataType);
            WebResponse.newInstance().buildModelMapData(modelMap);
        } catch (Exception e) {
            logger.error("", e);
            WebResponse.newInstance()
                    .setExceptionMsg(e)
                    .buildModelMapData(modelMap);
        }
        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @RequestMapping("/removeStepIdentity.html")
    public String removeStepIdentity(Map<String, Object> modelMap, Long taskActionDataTypeId) {
        try {
            TaskActionDataType taskActionDataType = taskActionDataTypeRepository.findOne(taskActionDataTypeId);
            taskActionDataType.remove();
            WebResponse.newInstance().buildModelMapData(modelMap);
        } catch (Exception e) {
            WebResponse.newInstance()
                    .setExceptionMsg(e)
                    .buildModelMapData(modelMap);
        }
        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @RequestMapping(value = "/stepIdentityList.html")
    public void stepIdentityList(Map modelMap) {
        modelMap.put("taskActionDataTypeList", taskActionDataTypeRepository.findAllActive());
        modelMap.put("taskAction", TaskAction.values());
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping(value = "/newStepForm.html")
    public void newStepForm(Map modelMap) {
        modelMap.put("taskAction", TaskAction.values());
        List<SalesScoringCategory> salesScoringCategories = salesScoringCategoryRepository.findAll(new Sort(Sort.Direction.ASC, "displayName"));
        modelMap.put("salesScoringCategories", salesScoringCategories);
    }

    @SuppressWarnings("rawtypes")
    @ResponseBody
    @RequestMapping(value = "/findTaskActionDataTypeByActionId.html")
    public Object findTaskActionDataTypeByActionId(Map modelMap, int actionId) {
        DateTime dateFrom = new DateTime().withTime(0, 0, 0, 0);
        DateTime dateTo = dateFrom.plusDays(1);
        List<TaskActionDataType> dDayList = taskActionDataTypeRepository.findActiveByActionIdAndUpdatedBetweenCloseOpen(actionId, dateFrom.toDate(), dateTo.toDate());
        List<TaskActionDataType> allList = taskActionDataTypeRepository.findActiveByActionId(actionId);
        List<TaskActionDataType> resultList = new LinkedList<TaskActionDataType>();
        if (dDayList.size() > 0) {
            resultList.addAll(dDayList);
            resultList.add(new TaskActionDataType(-1, "--------"));
        }
        resultList.addAll(allList);
        return resultList;
    }

    @SuppressWarnings({"rawtypes"})
    @RequestMapping(value = "/saveTaskStep.html")
    public String saveTaskStep(Map modelMap,
                               Integer actionId,
                               Long dataTypeId,
                               String actionName,
                               @RequestParam(required = false, defaultValue = "") String itemNames,
                               @RequestParam(required = false) String extData) {
        try {
            Task task = new Task(actionId, dataTypeId);
            String[] itemName = itemNames.split(";");
            int index = 0;
            for (String item : itemName) {
                if (!StringUtils.isEmpty(item)) {
                    TaskItem taskItem = task.createItem(item);
                    try {
                        if (extData != null && extData.trim().length() > 0) {
                            ObjectMapper mapper = new ObjectMapper();
                            List ext = mapper.readValue(extData, ArrayList.class);
                            if (ext.size() > index && ext.get(index) != null) {
                                Map data = (Map) ext.get(index);
                                taskItem.setExtra1(data.get("type").toString());
                                taskItem.setExtra2(data.get("point").toString());
                                taskItem.setExtra3(data.get("memo").toString());
                            }
                        }
                    } catch (Exception e) {
                        logger.error("", e);
                    }
                }
                index++;
            }
            task.setUpdatedAt(new Date());
            taskRepository.save(task);
            WebResponse.newInstance()
                    .buildModelMapData(modelMap);
        } catch (Exception e) {
            logger.error("", e);
            WebResponse.newInstance()
                    .setExceptionMsg(e)
                    .buildModelMapData(modelMap);
        }
        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @RequestMapping(value = "/stepList.html")
    public void stepList(Map modelMap) {
        modelMap.put("taskList", taskRepository.findAllActive());
    }

    @RequestMapping("removeStep.html")
    public String removeStep(Map<String, Object> modelMap, Long taskId) {
        try {
            Task task = taskRepository.findOne(taskId);
            task.remove();
            WebResponse.newInstance().buildModelMapData(modelMap);
        } catch (Exception e) {
            WebResponse.newInstance()
                    .setExceptionMsg(e)
                    .buildModelMapData(modelMap);
        }
        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @RequestMapping(value = "/newJobForm.html")
    public void newJobForm(Map modelMap) {
        modelMap.put("taskList", taskRepository.findAllActive());
    }

    @ResponseBody
    @RequestMapping(value = "/newJob.html")
    public Object newJob(@RequestBody Job job) {
        try {
        	if(job.getId()!=null && planJobRepository.findByJob(job).size()>0){
        		return WebResponse.newInstance().setSuccess(false).setMsgBody("任务已被使用无法修改");
        	}
            job.save();
            return WebResponse.newInstance();
        } catch (Exception e) {
            logger.error("", e);
            return WebResponse.newInstance().setExceptionMsg(e);
        }
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping(value = "/jobListData.html")
    public void jobList(Map modelMap,
                        @RequestParam(required = false) Long projectId,
                        Pageable pageable, HttpServletRequest request) {
        PageHandler p = null;
        if (projectId != null) {
            Project project = projectRepository.findOne(projectId);
            List<ProjectCriticalJob> criticalJobList = projectCriticalJobRepository.findByProject_Code(project.getCode());
            modelMap.put("criticalJobList", criticalJobList);
            modelMap.put("projectId", projectId);
            List<Job> jobs = project.getCategory().getJobs();
            String jobName = request.getParameter("jobName");
            if (jobName != null && !jobName.trim().isEmpty()) {
                jobName = jobName.trim();
                List<Job> jobList = jobs;
                jobs = new ArrayList<Job>();
                for (Job job : jobList) {
                    if (StringUtils.containsIgnoreCase(job.getName(), jobName)) {
                        jobs.add(job);
                    }
                }
            }
            int from = pageable.getOffset(), to = Math.min(jobs.size(), pageable.getOffset() + pageable.getPageSize());
            p = new PageHandler(pageable.getPageNumber(), jobs.size(), pageable.getPageSize(), jobs.subList(from, to));
        } else {
            Page<Job> page = jobRepository.findAll(PlanAssembler.toActiveCriteria(RequestUtil.getParameterMap(request)), pageable);
            p = new PageHandler(pageable.getPageNumber(),
                    Long.valueOf(page.getTotalElements()).intValue(),
                    pageable.getPageSize(),
                    page.getContent());
        }
        modelMap.put("page", p);
    }

    @RequestMapping("/removeJob.html")
    public String removeJob(Map<String, Object> modelMap, Long jobId) {
        try {
            Job job = jobRepository.findOne(jobId);
            job.remove();
            WebResponse.newInstance().buildModelMapData(modelMap);
        } catch (Exception e) {
            WebResponse.newInstance()
                    .setExceptionMsg(e)
                    .buildModelMapData(modelMap);
        }
        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping(value = "/newProjectTypeForm.html")
    public void newProjectTypeForm(Map modelMap) {
        modelMap.put("jobList", jobRepository.findAllActive());
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @RequestMapping(value = "/newProjectType.html")
    public String newProjectType(Map modelMap, String jobs, String categoryName, HttpServletRequest req) {
        ProjectCategory projCat = new ProjectCategory(categoryName);
        String[] jobsId = StringUtils.split(jobs, ";");
        for (int i = 0; i < jobsId.length; i++) {
            try {
                Job job = Job.findById(Long.valueOf(jobsId[i]));
                if (job != null) {
                    projCat.addJob(job);
                }
            } catch (Exception e) {
                logger.error("", e);
            }
        }
        try {
            adminService.storeProjectCategory(projCat);
        } catch (Exception e) {
            modelMap.put("error", e.getMessage());
            projectTypeEdit(modelMap, projCat.getId());
            return "/admin/newProjectTypeForm";
        }
        return "redirect:projectTypeList.html";
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @RequestMapping(value = "/projectTypeList.html")
    public void projectTypeList(Map modelMap) {
        modelMap.put("proCats", projCatRepo.findAll());
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @RequestMapping(value = "/projectTypeEdit.html")
    public void projectTypeEdit(Map modelMap, Long projCatId) {
        ProjectCategory projectCategory = projCatRepo.findOne(projCatId);
        modelMap.put("projectCategory", projectCategory);
        modelMap.put("jobList", jobRepository.findAll());
    }

    @SuppressWarnings({"rawtypes"})
    @RequestMapping(value = "/delprojectType.html")
    public String delprojectType(Map modelMap, Long projCatId) {
        ProjectCategory projCat = projCatRepo.findOne(projCatId);
        projCatRepo.delete(projCat);
        return "redirect:projectTypeList.html";
    }

    @SuppressWarnings({"rawtypes"})
    @RequestMapping(value = "/editProjectType.html")
    public String editProjectType(Map modelMap, String jobs, String categoryName, Long projCatId) {
        ProjectCategory projCat = projCatRepo.findOne(projCatId);
        List<Job> brandNewJobs = Lists.newArrayList();
        String[] jobsId = StringUtils.split(jobs, ";");
        for (int i = 0; i < jobsId.length; i++) {
            try {
                Job job = Job.findById(Long.valueOf(jobsId[i]));
                if (job != null) {
                    brandNewJobs.add(job);
                }
            } catch (Exception e) {
                logger.error("", e);
            }
        }
        projCat.setName(categoryName);
        projCat.setJobs(brandNewJobs);
        adminService.storeProjectCategory(projCat);
        return "redirect:projectTypeList.html";
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @RequestMapping(value = "/jobEdit.html")
    public void jobEdit(Map modelMap, Long jobId) {
        Job job = jobRepository.findOne(jobId);
        ObjectMapper mapper = new ObjectMapper();
        try {
            modelMap.put("jobJsonString", mapper.writeValueAsString(job));
        } catch (Exception e) {
            e.printStackTrace();
        }
        modelMap.put("job", job);
        modelMap.put("taskList", taskRepository.findAll());
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @RequestMapping(value = "/jobView.html")
    public String jobView(Map modelMap, Long jobId) {
        modelMap.put("read", "true");
        jobEdit(modelMap, jobId);
        return "admin/jobEdit";
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping(value = "/stepIdentityEditForm.html")
    public void stepIdentityEditForm(Map modelMap, Long id) {
        TaskActionDataType taskActionDataType = taskActionDataTypeRepository.findOne(id);
        modelMap.put("taskActionDataType", taskActionDataType);
    }

    @SuppressWarnings({"rawtypes"})
    @RequestMapping(value = "/stepIdentityEdit.html")
    public String stepIdentityEdit(Map modelMap, Long id, String actionName) {
        try {
            TaskActionDataType taskActionDataType = taskActionDataTypeRepository.findOne(id);
            taskActionDataType.setName(actionName);
            taskActionDataType.setUpdatedAt(new Date());
            taskActionDataTypeRepository.saveAndFlush(taskActionDataType);
            WebResponse.newInstance().buildModelMapData(modelMap);
        } catch (Exception e) {
            WebResponse.newInstance().setExceptionMsg(e).buildModelMapData(modelMap);
        }
        return WebResponse.GLOBAL_SUBMIT_CALLBACK_PAGE;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @RequestMapping(value = "/stepDetail.html")
    public void stepDetail(Map modelMap, Long id) {
        modelMap.put("task", taskRepository.findOne(id));
    }
}
